﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using CYTS.Aoyou.Framework.Utility;
using System.Threading;

namespace CYTS.Aoyou.Framework.Config
{
    /// <summary>
    /// 配置工厂
    /// </summary>
    public class ConfigFactory
    {
        private static Dictionary<string, ConfigUnit> ConfigUnitHash = new Dictionary<string, ConfigUnit>();
        //private static IList<ConfigUnit> _ConfigUnitList = new List<ConfigUnit>();
        private static readonly object StartLock = new object();

        private static bool _IsModified = false;
        public static event Action OnModified; 

        static ConfigFactory()
        {
            FileMonitorHelper.OnFileModified += FileMonitorHelper_OnFileModified;
            FileMonitorHelper.OnFileModifyCompleted += FileMonitorHelper_OnFileModifyCompleted;
        }

        /// <summary>
        /// 获得配置
        /// </summary>
        /// <typeparam name="T">配置类泛型</typeparam>
        /// <returns>配置实例</returns>
        public static T GetConfig<T>() where T : class
        {
            Type type = typeof(T);
            try
            {
                if (!ConfigUnitHash.ContainsKey(type.Name.ToLower()))
                {
                    GetConfigFromFile(type);
                }
                return (ConfigUnit)ConfigUnitHash[type.Name.ToLower()] as T;
            }
            catch (Exception ex)
            {
                string msg = string.Format("获取配置信息出现异常，ConfigType={0}", type.FullName);
                throw new Exception(msg, ex);
            }
        }

        /// <summary>
        /// 强制从本地文件重新加载配置；
        /// 仅重新加载已经加载过的配置，因为没有加载过的配置在第一次使用时会去加载最新配置文件到内存；
        /// </summary>
        public static void LoadConfigManually()
        {
            foreach (var unitKvp in ConfigUnitHash)
            {
                UpdateOneConfig(unitKvp.Value);
            }
        }


        /// <summary>
        /// 获取当前应用内存中所有已经加载的ConfigUnit
        /// </summary>
        /// <returns></returns>
        public static IList<ConfigUnit> GetAllConfigUnitListInMemory()
        {
            return ConfigUnitHash.Values.Select(p => (ConfigUnit)p).ToList();
        }


        static void FileMonitorHelper_OnFileModifyCompleted()
        {
            if (_IsModified)
            {
                if (OnModified != null)
                {
                    OnModified();
                }
                _IsModified = false;
            }
        }

        static void FileMonitorHelper_OnFileModified(FileInfo file)
        {
            if (file.Extension.ToLower() == ".config")
            {
                ConfigUnit unit = null;
                if (ConfigUnitHash.TryGetValue(file.Name.ToLower().Replace(".config", "config"), out unit))
                {
                    UpdateOneConfig(unit);
                    _IsModified = true;
                }
            }
        }

        private static void GetConfigFromFile(Type configType)
        {
            try
            {
                Monitor.Enter(StartLock);
                #region 将配置实例加入配置列表

                //如果有其他线程将配置加载到内存了，那么不需要再次加载配置
                if (ConfigUnitHash.ContainsKey(configType.Name.ToLower()))
                {
                    return;
                }

                Type baseType = typeof(ConfigUnit);
                if (configType.IsSubclassOf(baseType))
                {
                    ConfigUnit cu = (ConfigUnit)Activator.CreateInstance(configType);

                    //从本地配置文件加载配置到内存

                    //=====开始加载配置（本地文件）=====

                    UpdateOneConfig(cu);

                    //=====完成加载配置（本地文件）=====
                }
                else
                {
                    string msg = string.Format("传入参数配置类型‘{0}’不是配置基类‘{1}’的子类！", configType.FullName, baseType.FullName);
                    throw new Exception(msg);
                }

                #endregion


            }
            catch (Exception ex)
            {
                string msg = "GetConfigFromFile错误 将无法获取对应的数据！";
                throw new Exception(msg, ex);
            }
            finally
            {
                Monitor.Exit(StartLock);
            }
        }

        ///// <summary>
        ///// 将_ConfigUnitList中的每个ConfigUnit重新加载一次，并更新到_ConfigUnitHash中；
        ///// </summary>
        //private static void OnFileUpdate()
        //{
        //    foreach (ConfigUnit unit in _ConfigUnitList)
        //    {
        //        UpdateOneConfig(unit);
        //    }
        //}

        private static bool UpdateOneConfig(ConfigUnit unit)
        {
            bool retVal = true;
            try
            {
                var unitTemp = unit.OnUpdate();

                //更新_ConfigUnitHash，将配置实例的透明代理放到hash中
                ConfigUnitHash[unitTemp.GetType().Name.ToLower()] = unitTemp;
            }
            catch (Exception ex)
            {
                retVal = false;
                string msg = "UpdateOneConfig失败";
                throw new Exception(msg, ex);
            }
            return retVal;
        }
    }
}
